﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace TathamOddie.OpenSearchValidator.Logic.Tasks
{
    public abstract class InterfaceDiscoveryTask : IValidationTask
    {
        readonly string interfaceName;
        readonly string interfaceMediaType;
        readonly string descriptionXml;

        public InterfaceDiscoveryTask(string interfaceName, string interfaceMediaType, string descriptionXml)
        {
            this.interfaceName = interfaceName;
            this.interfaceMediaType = interfaceMediaType;
            this.descriptionXml = descriptionXml;
        }

        public ValidationTaskResult Validate(ValidationServices services, ValidationState state)
        {
            var result = new ValidationTaskResult();

            var document = new XmlDocument();
            document.LoadXml(descriptionXml);

            var namespaceManager = new XmlNamespaceManager(document.NameTable);
            namespaceManager.AddNamespace("osd", document.DocumentElement.NamespaceURI);

            var links = document.SelectNodes(
                string.Format("/osd:OpenSearchDescription/osd:Url[@type='{0}']", interfaceMediaType),
                namespaceManager);

            if (links.Count == 0)
            {
                result.AddMessage(MessageType.Information,
                    string.Format("No {0} interfaces were found in the OpenSearch description. We searched for a <Url /> node with the 'type' attribute set to 'application/x-suggestions+xml' but none was found. Adding an XML search interface will provide search suggestions for Internet Explorer 8 users.", interfaceName));
            }
            else if (links.Count > 1)
            {
                result.AddMessage(MessageType.Failure,
                    string.Format("Multiple {0} interfaces were found in the OpenSearch description.", interfaceName));
            }
            else
            {
                var interfaceTemplate = links[0].Attributes["template"].Value;

                if (string.IsNullOrEmpty(interfaceTemplate))
                {
                    result.AddMessage(MessageType.Failure,
                        "A {0} interface was found in the OpenSearch description however no template was specified.",
                        interfaceName);
                }
                else
                {
                    Uri interfaceTemplateUri;
                    bool parsed = Uri.TryCreate(interfaceTemplate, UriKind.Absolute, out interfaceTemplateUri);

                    if (parsed)
                    {
                        result.AddMessage(MessageType.Success,
                            "A {0} interface [{1}] was found in the OpenSearch description.",
                            interfaceName,
                            interfaceTemplateUri);
                        OnValidateSuccess(result, interfaceTemplate);
                    }
                    else
                    {
                        result.AddMessage(MessageType.Failure,
                            "A {0} interface was found in the OpenSearch description with template [{0}] however this value could not be parsed as an absolute URI.",
                            interfaceTemplate);
                    }
                }
            }

            return result;
        }

        protected virtual void OnValidateSuccess(ValidationTaskResult result, string interfaceTemplate)
        {
        }
    }
}